package common.main.google;

import common.http.HtmlInfo;
import org.apache.http.HttpHost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HttpClientUtil {
    // 依次是代理地址，代理端口号，用户密码
   /* private static String proxyHost="192.168.3.92";
    private static int proxyPort=1080;
    private static String proxyName=null;
    private static String proxyPwd=null;*/


    public static void getWithProxy(HtmlInfo html/*String url, Map<String, String> headers, String charset*/) {
        String url = html.getOrignUrl();
        String charset = html.getEncode();
        Map<String,String> headers = new HashMap<>();
        //用户名和密码验证
        Authenticator.setDefault(new Authenticator(){
            protected  PasswordAuthentication  getPasswordAuthentication(){
                PasswordAuthentication p=new PasswordAuthentication(Config.proxyName, Config.proxyPwd.toCharArray());
                return p;
            }
        });
        Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory> create()
                .register("http", new MyConnectionSocketFactory())
                .register("https", new MySSLConnectionSocketFactory(SSLContexts.createSystemDefault())).build();
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(reg, new FakeDnsResolver());
        CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(cm).build();
        try {
            InetSocketAddress socksaddr = new InetSocketAddress(Config.proxyHost,Config.proxyPort);
            HttpClientContext context = HttpClientContext.create();
            context.setAttribute("socks.address", socksaddr);
            HttpGet httpget = new HttpGet(url);
            if (html.getAccept() != null) {
                //设置请求头 accept
                httpget.setHeader("Accept", html.getAccept());
            }
            if (html.getUa() != null) {
                //设置请求头 user agent
                httpget.setHeader("User-Agent", html.getUa());
            }
            //设置请求头 connection
            httpget.setHeader("Connection", "keep-alive");
            if (html.getHost() != null) {
                //设置请求头 host
                httpget.setHeader("Host", html.getHost());
            }
            if (html.getCookie() != null) {
                //设置请求头 cookie
                httpget.setHeader("Cookie", html.getCookie());
            }
            if (html.getReferUrl() != null) {
                //设置请求头 referer
                httpget.setHeader("Referer", html.getReferUrl());
            }
            if (html.getAcceptEncoding() != null) {
                //设置请求头 referer  Upgrade-Insecure-Requests: 1
                httpget.setHeader("Accept-Encoding", html.getAcceptEncoding());
            }

            //:
            httpget.setHeader("Accept-Language", "zh-CN,zh;q=0.8,en-us;q=0.6,en;q=0.5;q=0.4");
            if(html.getHeadMap()!=null&&html.getHeadMap().size()>0){
                Set<String> keys = html.getHeadMap().keySet();
                for(String key:keys){
                    httpget.setHeader(key,html.getHeadMap().get(key));
                }
            }
            if(headers != null) {
                for(String key:headers.keySet()) {
                    httpget.setHeader(key, headers.get(key));
                }
            }
            CloseableHttpResponse response = httpclient.execute(httpget,context);
            try {
                html.setContent(new String(EntityUtils.toByteArray(response.getEntity()), charset));
                //return new String(EntityUtils.toByteArray(response.getEntity()), charset);
            } finally {
                response.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpclient.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        //return null;
    }
    static class FakeDnsResolver implements DnsResolver {

        public InetAddress[] resolve(String host) throws UnknownHostException {
            // Return some fake DNS record for every request, we won't be using it
            return new InetAddress[] { InetAddress.getByAddress(new byte[] { 1, 1, 1, 1 }) };
        }
    }

    static class MyConnectionSocketFactory extends PlainConnectionSocketFactory {
        @Override
        public Socket createSocket(final HttpContext context) throws IOException {
            InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address");
            Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
            return new Socket(proxy);
        }

        @Override
        public Socket connectSocket(int connectTimeout, Socket socket, HttpHost host, InetSocketAddress remoteAddress,
                                    InetSocketAddress localAddress, HttpContext context) throws IOException {
            // Convert address to unresolved
            InetSocketAddress unresolvedRemote = InetSocketAddress
                    .createUnresolved(host.getHostName(), remoteAddress.getPort());
            return super.connectSocket(connectTimeout, socket, host, unresolvedRemote, localAddress, context);
        }
    }

    static class MySSLConnectionSocketFactory extends SSLConnectionSocketFactory {

        public MySSLConnectionSocketFactory(final SSLContext sslContext) {
            // You may need this verifier if target site's certificate is not secure
            super(sslContext, ALLOW_ALL_HOSTNAME_VERIFIER);
        }

        @Override
        public Socket createSocket(final HttpContext context) throws IOException {
            InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address");
            Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
            return new Socket(proxy);
        }

        @Override
        public Socket connectSocket(int connectTimeout, Socket socket, HttpHost host, InetSocketAddress remoteAddress,
                                    InetSocketAddress localAddress, HttpContext context) throws IOException {
            // Convert address to unresolved
            InetSocketAddress unresolvedRemote = InetSocketAddress
                    .createUnresolved(host.getHostName(), remoteAddress.getPort());
            return super.connectSocket(connectTimeout, socket, host, unresolvedRemote, localAddress, context);
        }
    }

}
